package com.zts.modules.sys.service.impl;

import com.google.common.base.Strings;
import com.zts.base.exception.InternalServerErrorException;
import com.zts.base.exception.InvalidArgumentException;
import com.zts.base.exception.SourceNotFoundException;
import com.zts.base.exception.UnprocessableEntityException;
import com.zts.base.page.PageBound;
import com.zts.common.Constant;
import com.zts.modules.sys.entity.Resource;
import com.zts.modules.sys.entity.Role;
import com.zts.modules.sys.entity.User;
import com.zts.modules.sys.mapper.RoleMapper;
import com.zts.modules.sys.service.GroupService;
import com.zts.modules.sys.service.ResourceService;
import com.zts.modules.sys.service.RoleService;
import com.zts.modules.sys.service.UserService;
import com.zts.util.BeanUtil;
import com.zts.util.BeanValidatorsUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by lily on 2017/6/13.
 */
@Service
public class RoleServiceImpl implements RoleService {
    @Autowired
    RoleMapper roleMapper;

    @Autowired
    UserService userService;

    @Autowired
    GroupService groupService;

    @Autowired
    ResourceService resourceService;

    /**
     * 根据主键查询
     *
     * @param id
     * @return
     */
    @Override
    public Role get(Long id) {
        if (null == id || id < 0) {
            throw new IllegalArgumentException("参数<id>为空");
        }
        Role role = roleMapper.get(id);
        if (null == role) {
            throw new SourceNotFoundException("id[" + id + "]对应的角色未找到！");
        }
        return role;
    }

    /**
     * 根据关键字查询
     *
     * @param entity
     * @return
     */
    @Override
    public List<Role> getByEntity(Role entity) {
        if (null == entity) {
            throw new IllegalArgumentException("参数对象为空");
        }
        if (Strings.isNullOrEmpty(entity.getRoleName()) && Strings.isNullOrEmpty(entity.getType())) {
            throw new IllegalArgumentException("角色名称和角色类型不能同时为空");
        }
        List<Role> roleList = roleMapper.getByEntity(entity);
        if (null == roleList || roleList.size() == 0) {
            throw new SourceNotFoundException("未找到对应的角色！");
        }
        return roleList;
    }


    @Override
    public List<Role> getByCondition(Map<String, Object> conditions) {
        //TODO:暂不实现
        return null;
    }

    /**
     * 条件查询返回分页数据
     *
     * @param entity
     * @param pageBound
     * @return
     */
    @Override
    public List<Role> getList(Role entity, PageBound pageBound) {
        if (null == entity) {
            entity = new Role();
        }
        return roleMapper.getList(entity, pageBound);
    }

    /**
     * 新增
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional
    public Role insert(Role entity) {
        if (null == entity) {
            throw new IllegalArgumentException("参数对象为空");
        }
        //保存前先校验
        BeanValidatorsUtil.validateWithException(entity);
        int i = roleMapper.insert(entity);
        if (i < 0 || null == entity.getId()) {
            throw new InternalServerErrorException("保存失败");
        }
        return roleMapper.get(entity.getId());
    }

    /**
     * 根据主键id更新
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional
    public int update(Role entity) {
        if (null == entity || null == entity.getId() || entity.getId() < 0) {
            throw new IllegalArgumentException("参数对象或参数<id>为空");
        }
        //更新前先校验
        Role old = roleMapper.get(entity.getId());
        if (null == old) {
            throw new SourceNotFoundException("id[" + entity.getId() + "]对应的角色不存在！");
        }
        BeanUtils.copyProperties(entity, old, BeanUtil.getNullPropertyNames(entity));
        BeanValidatorsUtil.validateWithException(old);
        return roleMapper.update(old);
    }

    /**
     * 删除记录（逻辑删除）
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional
    public int delete(Role entity) {
        if (null == entity || null == entity.getId() || entity.getId() < 0) {
            throw new IllegalArgumentException("参数对象或参数<id>为空");
        }
        //删除前校验开始
        if (!checkStatus(entity.getId())) {
            throw new InvalidArgumentException("id[" + entity.getId() + "]对应的角色状态无效！");
        }
        //该角色下是否存在用户user或组group
        if (isUsed(entity.getId())) {
            throw new UnprocessableEntityException("当前角色[" + entity.getRoleName() + "]正在被使用，不允许删除！");
        }
        return roleMapper.delete(entity);
    }

    @Override
    @Transactional
    public Role save(Role entity) {
        if (null == entity) {
            throw new IllegalArgumentException("参数为空！");
        }
        if (null == entity.getId() || entity.getId() < 0) {
            //id不存在，则执行新增操作
            return insert(entity);
        } else {
            //id存在，则执行更新操作
            update(entity);
            return get(entity.getId());
        }
    }

    /**
     * 当前角色是否被使用
     *
     * @param id
     * @return
     */
    public boolean isUsed(Long id) {
        if (null == id || id < 0) {
            throw new IllegalArgumentException("参数<id>为空");
        }
        if (!checkStatus(id)) {
            throw new InvalidArgumentException("id[" + id + "]对应的角色状态无效！");
        }
        return roleMapper.isUserd(id);
    }

    /**
     * 查询拥有当前角色的直接用户，包括两部分：
     * 1：直接给user授权方式时的用户；
     * 2：给group授权方式时该group下的直接用户，且单独撤销授权的用户除外
     *
     * @param id 角色id
     * @return
     */
    public List<User> getUsers(Long id) {
        if (null == id || id < 0) {
            throw new IllegalArgumentException("参数<id>为空");
        }
        if (!checkStatus(id)) {
            throw new InvalidArgumentException("id[" + id + "]对应的角色状态无效！");
        }
        return roleMapper.getUsers(id);
    }

    /**
     * 查询拥有当前角色的所有用户，包括两部分：
     * 1：直接给user授权方式时的用户；
     * 2：给group授权方式时该group下的所有用户，包括该group的下级组，且单独撤销授权的用户除外
     *
     * @param id 角色id
     * @return
     */
    public List<User> getAllUsers(Long id) {
        if (null == id || id < 0) {
            throw new IllegalArgumentException("参数<id>为空");
        }
        if (!checkStatus(id)) {
            throw new InvalidArgumentException("id[" + id + "]对应的角色状态无效！");
        }
        return roleMapper.getAllUsers(id);
    }

    /**
     * 状态是否有效
     *
     * @param id
     * @return
     */
    public boolean checkStatus(Long id) {
        if (null == id || id <= 0) {
            throw new IllegalArgumentException("参数<id>为空");
        }
        Role role = get(id);
        if (null == role) {
            throw new SourceNotFoundException("id[" + id + "]对应的角色不存在！");
        }
        if (!Constant.STATUS_VALID.equals(role.getStatus())) {
            return false;
        }
        return true;
    }

    /**
     * 删除用户的grant_type=撤销权限  的记录
     * 一般用于 将用户从组中删除时
     *
     * @param userId
     * @param groupId
     * @return
     */
    @Transactional
    public int deleteRoleByUserAndGroup(Long userId, Long groupId) {
        if (null == userId || userId < 0) {
            throw new IllegalArgumentException("参数<userId>为空");
        }
        if (null == groupId || groupId < 0) {
            throw new IllegalArgumentException("参数<groupId>为空");
        }
        return roleMapper.deleteRoleByUserAndGroup(userId, groupId);
    }

    /**
     * 批量删除多个用户的grant_type=撤销权限  的记录
     * 一般用于 将用户从组中删除时
     *
     * @param userIds
     * @param groupId
     * @return
     */
    @Transactional
    public int deleteRoleByUsersAndGroup(List<Long> userIds, Long groupId) {
        if (null == userIds || userIds.size() <= 0) {
            throw new IllegalArgumentException("参数<userIds>为空");
        }
        if (null == groupId || groupId < 0) {
            throw new IllegalArgumentException("参数<groupId>为空");
        }
        return roleMapper.deleteRoleByUsersAndGroup(userIds, groupId);
    }

    /**
     * 用户或组单一授权
     *
     * @param objectId
     * @param objectType '被授权对象类型，1：部门，2：用户';
     * @param roleId
     * @param grantType  1：增加权限;0:撤销权限'
     * @return
     */
    @Transactional
    public int singleGrant(Long objectId, String objectType, Long roleId, String grantType) {
        checkParas(objectId, objectType, roleId, grantType);
        //校验角色是否有效
        if (!checkStatus(roleId)) {
            throw new InvalidArgumentException("id[" + roleId + "]对应的角色状态无效");
        }
        //校验授权是否存在
        if (checkGrantExist(objectId, objectType, roleId, grantType)) {
            throw new InvalidArgumentException("该授权已存在！");
        }
        return roleMapper.singleGrant(objectId, objectType, roleId, grantType);
    }

    public void checkParas(Long objectId, String objectType, Long roleId, String grantType) {
        List<Long> roleIds = new ArrayList<>();
        roleIds.add(roleId);
        checkParas(objectId, objectType, roleIds, grantType);

    }

    public void checkParas(Long objectId, String objectType, List<Long> roleIds, String grantType) {
        if (null == objectId || objectId <= 0) {
            throw new IllegalArgumentException("授权对象id<objectId>为空");
        }
        if (Strings.isNullOrEmpty(objectType)) {
            throw new IllegalArgumentException("授权对象类型<objectType>为空");
        }
        if (!Constant.GRANT_OBJECT_GROUP.equals(objectType) && !Constant.GRANT_OBJECT_USER.equals(objectType)) {
            throw new IllegalArgumentException("授权对象类型<objectType>不合法");
        }
        if (null == roleIds || roleIds.size() <= 0) {
            throw new IllegalArgumentException("授权角色列表<roleIds>为空");
        }
        if (Strings.isNullOrEmpty(grantType)) {
            throw new IllegalArgumentException("授权类型<grantType>为空");
        }
        if (!Constant.GRANT_TYPE_ASSIGN.equals(grantType) && !Constant.GRANT_TYPE_REVOKE.equals(grantType)) {
            throw new IllegalArgumentException("授权类型<grantType>不合法");
        }
        //校验被授权对象是否存在或有效
        if (Constant.GRANT_OBJECT_USER.equals(objectType) && !userService.checkStatus(objectId)) {
            throw new InvalidArgumentException("id[" + objectId + "]对应的用户状态无效");
        }
        if (Constant.GRANT_OBJECT_GROUP.equals(objectType) && !groupService.checkStatus(objectId)) {
            throw new InvalidArgumentException("id[" + objectId + "]对应的组状态无效");
        }
    }

    /**
     * 用户或组批量授权
     *
     * @param objectId
     * @param objectType
     * @param roleIds
     * @param grantType
     * @return
     */
    @Transactional
    public int batchGrant(Long objectId, String objectType, List<Long> roleIds, String grantType) {
        checkParas(objectId, objectType, roleIds, grantType);
        //校验角色状态是否有效;校验授权是否存在
        for (int i = 0; i < roleIds.size(); i++) {
            if (!checkStatus(roleIds.get(i)))
                throw new InvalidArgumentException("id[" + roleIds.get(i) + "]对应的角色状态无效!");
            if (checkGrantExist(objectId, objectType, roleIds.get(i), grantType)) {
                throw new InvalidArgumentException("对象[" + objectId + "]已存在授权[" + roleIds.get(i) + "]!");
            }
        }

        return roleMapper.batchGrant(objectId, objectType, roleIds, grantType);
    }

    /**
     * 用户或组删除单一角色
     *
     * @param objectId
     * @param objectType
     * @param roleId
     * @param grantType
     * @return
     */
    @Transactional
    public int singleGrantDelete(Long objectId, String objectType, Long roleId, String grantType) {
        checkParas(objectId, objectType, roleId, grantType);
        //校验是否存在此授权
        if (!checkGrantExist(objectId, objectType, roleId, "1")) {
            throw new SourceNotFoundException("不存在此授权！");
        }
        return roleMapper.singleGrantDelete(objectId, objectType, roleId, grantType);
    }


    /**
     * 用户或组批量撤销多个角色
     *
     * @param objectId
     * @param objectType
     * @param roleIds
     * @param grantType
     * @return
     */
    @Transactional
    public int batchGrantDelete(Long objectId, String objectType, List<Long> roleIds, String grantType) {
        checkParas(objectId, objectType, roleIds, grantType);
        //校验是否存在此授权
        for (int i = 0; i < roleIds.size(); i++) {
            if (!checkGrantExist(objectId, objectType, roleIds.get(i), Constant.GRANT_TYPE_ASSIGN)) {
                if (Constant.GRANT_OBJECT_GROUP.equals(objectType)) {
                    throw new InvalidArgumentException("组[" + objectId + "]不存在授权[" + roleIds.get(i) + "]!");
                } else {
                    throw new InvalidArgumentException("用户[" + objectId + "]不存在授权[" + roleIds.get(i) + "]!");
                }
            }
        }
        return roleMapper.batchGrantDelete(objectId, objectType, roleIds, grantType);
    }

    /**
     * 给组授权，组下某些用户除外
     *
     * @param groupId
     * @param roleId
     * @param userIds
     * @return
     */
    @Transactional
    public int groupGrantExcludeUsers(Long groupId, Long roleId, List<Long> userIds) {
        //若userIds非空，校验userIds是否是在组groupId中
        if (null != userIds && userIds.size() > 0) {
            for (int i = 0; i < userIds.size(); i++) {
                if (!groupService.checkUserGroupExist((userIds.get(i)), groupId, "false"))
                    throw new InvalidArgumentException("用户[" + userIds.get(i) + "]不是组[" + groupId + "]的用户");
            }
        }
        //给组授权
        singleGrant(groupId, "1", roleId, "1");
        if (null != userIds && userIds.size() > 0) {
            //批量增加 userIds 的 类型=撤销权限的角色 记录
            //objectType='2' 用户；grantType = ‘0’ 撤销权限
            batchGrantForObjs(userIds, "2", roleId, "0");
        }
        return 1;
    }

    /**
     * 给多个用户或组单个授权
     *
     * @param objectIds
     * @param objectType
     * @param roleId
     * @param grantType
     * @return
     */
    @Transactional
    public int batchGrantForObjs(List<Long> objectIds, String objectType, Long roleId, String grantType) {
        if (null == objectIds || objectIds.size() <= 0) {
            throw new IllegalArgumentException("被授权对象<objectIds>为空");
        }
        if (Strings.isNullOrEmpty(objectType)) {
            throw new IllegalArgumentException("授权对象类型<objectType>为空");
        }
        if (!"1".equals(objectType) && !"2".equals(objectType)) {
            throw new IllegalArgumentException("授权对象类型<objectType>不合法");
        }
        if (null == roleId || roleId < 0) {
            throw new IllegalArgumentException("授权角色id<roleId>为空");
        }
        if (Strings.isNullOrEmpty(grantType)) {
            throw new IllegalArgumentException("授权类型<grantType>为空");
        }
        if (!"1".equals(grantType) && !"0".equals(grantType)) {
            throw new IllegalArgumentException("授权类型<grantType>不合法");
        }
        return roleMapper.batchGrantForObjs(objectIds, objectType, roleId, grantType);

    }

    /**
     * 校验授权是否存在
     *
     * @param objectId
     * @param objectType
     * @param roleId
     * @param grant_type
     * @return
     */
    public boolean checkGrantExist(Long objectId, String objectType, Long roleId, String grant_type) {
        if (null == objectId || objectId < 0) {
            throw new IllegalArgumentException("授权对象id<objectId>为空");
        }
        if (Strings.isNullOrEmpty(objectType)) {
            throw new IllegalArgumentException("授权对象类型<objectType>为空");
        }
        if (!Constant.GRANT_OBJECT_GROUP.equals(objectType) && !Constant.GRANT_OBJECT_USER.equals(objectType)) {
            throw new IllegalArgumentException("授权对象类型<objectType>不合法");
        }
        if (null == roleId || roleId <= 0) {
            throw new IllegalArgumentException("授权角色id<roleId>为空");
        }
        return roleMapper.checkGrantExist(objectId, objectType, roleId, grant_type);
    }

    /**
     * 查看用户直接拥有的角色
     *
     * @param userId
     * @return
     */
    public List<Role> getRolesByUserId(Long userId) {
        if (null == userId || userId < 0) {
            throw new IllegalArgumentException("参数<userId>为空");
        }
        return roleMapper.getRolesByUserId(userId);
    }

    /**
     * 查看用户拥有的所有角色，包括所在组（group)以及上级组拥有的角色
     *
     * @param userId
     * @return
     */
    public List<Role> getAllRolesByUserId(Long userId) {
        if (null == userId || userId < 0) {
            throw new IllegalArgumentException("参数<userId>为空");
        }
        return roleMapper.getAllRolesByUserId(userId);
    }

    /**
     * 查看组直接拥有的角色
     *
     * @param groupId
     * @return
     */
    public List<Role> getRolesByGroupId(Long groupId) {
        if (null == groupId || groupId < 0) {
            throw new IllegalArgumentException("参数<groupId>为空");
        }
        return roleMapper.getRolesByGroupId(groupId);
    }

    /**
     * 查看组拥有的所有角色，包括组（group)的递归上级组拥有的角色
     *
     * @param groupId
     * @return
     */
    public List<Role> getAllRolesByGroupId(Long groupId) {
        if (null == groupId || groupId < 0) {
            throw new IllegalArgumentException("参数<groupId>为空");
        }
        return roleMapper.getAllRolesByGroupId(groupId);
    }

    /**
     * 查看角色拥有的资源
     *
     * @param roleId
     * @return
     */
    public List<Resource> getResources(Long roleId) {
        if (null == roleId || roleId < 0) {
            throw new IllegalArgumentException("参数<roleId>为空");
        }
        if (!checkStatus(roleId)) {
            throw new InvalidArgumentException("角色[" + roleId + "]状态无效！");
        }
        List<Resource> resourceList = resourceService.getByRoles(roleId, "");
        if (null == resourceList || resourceList.size() <= 0) {
            throw new SourceNotFoundException("角色[" + roleId + "]下目前未分配任何资源！");
        }
        return resourceList;
    }
}
